Object Relational Mapping (ORM) প্রযুক্তি যেমন Hibernate বা JPA ব্যবহার করে ডেটাবেসের টেবিল এবং জাভা অবজেক্টের মধ্যে সম্পর্ক স্থাপন করা হয়। Entity Design হল ORM ব্যবহারের একটি গুরুত্বপূর্ণ অংশ, যা ডেটাবেসের কাঠামো এবং ডেভেলপমেন্ট প্রক্রিয়াকে সহজ এবং কার্যকর করে তোলে। তবে Entity Design করার সময় কিছু Best Practices অনুসরণ করা অত্যন্ত গুরুত্বপূর্ণ, যাতে ডেটাবেস অপারেশনগুলো দ্রুত এবং সহজভাবে পরিচালিত হয়।
Entity ক্লাস এবং টেবিল নামের মধ্যে সঙ্গতি রাখা গুরুত্বপূর্ণ। সাধারণত, Entity ক্লাসের নাম এবং টেবিল নাম একই রাখা উচিত। স্প্রিং ORM এবং Hibernate ডিফল্টভাবে ক্লাসের নাম অনুযায়ী টেবিলের নাম গঠন করে।
@Entity
@Table(name = "employee")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String department;
// Getters and Setters
}
এখানে, Employee
ক্লাসের সাথে employee
টেবিলের নাম মেলে।
Entity ক্লাসের প্রপার্টি গুলি টেবিলের কলামের সাথে সঙ্গতিপূর্ণ হতে হবে। স্প্রিং ORM এবং Hibernate সাধারণত এটি অটোমেটিকভাবে ম্যাপ করে, তবে যদি প্রয়োজন হয়, তখন @Column অ্যানোটেশন ব্যবহার করে কলামের নাম পরিবর্তন করা যেতে পারে।
@Column(name = "emp_name")
private String name;
এখানে, name
প্রপার্টি emp_name
নামের কলামের সাথে ম্যাপ করা হচ্ছে।
প্রতিটি Entity ক্লাসে একটি Primary Key থাকতে হবে, যা সাধারণত @Id
অ্যানোটেশন দিয়ে চিহ্নিত করা হয়। GeneratedValue ব্যবহার করে Primary Key এর মান অটোমেটিকভাবে জেনারেট করা যায়।
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
এতে, id
ফিল্ডটি ডাটাবেসে স্বয়ংক্রিয়ভাবে জেনারেট হবে।
Entity গুলোর মধ্যে সম্পর্ক স্থাপন করা খুব গুরুত্বপূর্ণ। স্প্রিং ORM এবং Hibernate এ বিভিন্ন ধরনের সম্পর্কের জন্য সুনির্দিষ্ট অ্যানোটেশন রয়েছে, যেমন:
উদাহরণস্বরূপ:
@Entity
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "department")
private List<Employee> employees;
// Getters and Setters
}
এখানে, Department
ক্লাসে একটি One-to-Many সম্পর্ক তৈরি করা হয়েছে, যেখানে একটি Department
অনেক Employee
এর সাথে সম্পর্কিত।
Hibernate বা JPA-তে লেনদেনের সময় Lazy Loading এবং Eager Loading ব্যবহার করা হয় সম্পর্কযুক্ত Entity গুলোর লোডিং কন্ট্রোল করতে। Lazy Loading ব্যবহার করলে সম্পর্কযুক্ত Entity গুলো শুধুমাত্র প্রয়োজন হলে লোড হবে, আর Eager Loading ব্যবহার করলে সম্পর্কযুক্ত Entity গুলো একসাথে লোড হবে।
@OneToMany(fetch = FetchType.LAZY)
private List<Employee> employees;
এখানে, employees
ফিল্ডটি Lazy Loading
মোডে লোড হবে।
ডেটাবেসের টেবিলের Entity ক্লাস সরাসরি API বা ইউজার ইন্টারফেসের সাথে সংযুক্ত না করা উচিত। এর পরিবর্তে DTO ব্যবহার করা উচিত। DTO Entity ক্লাসের ডেটাকে প্রেজেন্টেশনের জন্য উপযোগী করে পরিবেশন করে।
public class EmployeeDTO {
private String name;
private String department;
// Constructor, Getters, and Setters
}
এতে, আপনি Entity ক্লাসের ডেটা DTO তে ট্রান্সফার করে প্রক্রিয়াটি আরও পরিষ্কার এবং সিস্টেমের নিরাপত্তা উন্নত করতে পারেন।
ডেটাবেসের টেবিলের জন্য সীমিত মান (এনাম) ব্যবহার করতে @Enumerated অ্যানোটেশন ব্যবহার করা যেতে পারে। এটি ডেটাবেসে সাধারণ স্ট্রিং ভ্যালু পরিবর্তে এনামের মান সংরক্ষণ করতে সহায়তা করে।
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Enumerated(EnumType.STRING)
private EmploymentType employmentType;
// Getters and Setters
}
public enum EmploymentType {
FULL_TIME,
PART_TIME
}
এখানে, employmentType
ফিল্ডটি FULL_TIME
অথবা PART_TIME
এনাম দিয়ে ধারণ করা হবে।
Entity Design এর সময় ডেটাবেস ট্রানজেকশন ম্যানেজমেন্টের বিষয়টি মাথায় রাখা উচিত। স্প্রিং ORM এ @Transactional অ্যানোটেশন ব্যবহার করে কার্যকর ট্রানজেকশন ম্যানেজমেন্ট করা যায়।
@Service
@Transactional
public class EmployeeService {
@Autowired
private EmployeeRepository employeeRepository;
public void saveEmployee(Employee employee) {
employeeRepository.save(employee);
}
}
এটি নিশ্চিত করে যে, ডেটাবেস অপারেশন একক ট্রানজেকশন হিসেবে পরিচালিত হবে এবং কোনো ত্রুটি ঘটলে তা রোলব্যাক হবে।
স্প্রিং ORM এ Entity Design করার জন্য কিছু গুরুত্বপূর্ণ Best Practices রয়েছে, যেমন Entity ক্লাসের নাম ও টেবিল নামের সঙ্গতি বজায় রাখা, Relationships সঠিকভাবে ম্যানেজ করা, Lazy এবং Eager Loading ব্যবহারে সঠিক সিদ্ধান্ত নেওয়া, DTO ব্যবহার করা, এবং ট্রানজেকশন ম্যানেজমেন্ট নিশ্চিত করা। এগুলোর মাধ্যমে আপনি কার্যকর ও সুসংগঠিত ডেটাবেস কাঠামো তৈরি করতে পারবেন, যা অ্যাপ্লিকেশনকে আরও স্কেলেবল এবং মেইনটেইনেবল করে তোলে।
Object Relational Mapping (ORM) প্রযুক্তি যেমন Hibernate বা JPA ব্যবহার করে ডেটাবেসের টেবিল এবং জাভা অবজেক্টের মধ্যে সম্পর্ক স্থাপন করা হয়। Entity Design হল ORM ব্যবহারের একটি গুরুত্বপূর্ণ অংশ, যা ডেটাবেসের কাঠামো এবং ডেভেলপমেন্ট প্রক্রিয়াকে সহজ এবং কার্যকর করে তোলে। তবে Entity Design করার সময় কিছু Best Practices অনুসরণ করা অত্যন্ত গুরুত্বপূর্ণ, যাতে ডেটাবেস অপারেশনগুলো দ্রুত এবং সহজভাবে পরিচালিত হয়।
Entity ক্লাস এবং টেবিল নামের মধ্যে সঙ্গতি রাখা গুরুত্বপূর্ণ। সাধারণত, Entity ক্লাসের নাম এবং টেবিল নাম একই রাখা উচিত। স্প্রিং ORM এবং Hibernate ডিফল্টভাবে ক্লাসের নাম অনুযায়ী টেবিলের নাম গঠন করে।
@Entity
@Table(name = "employee")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String department;
// Getters and Setters
}
এখানে, Employee
ক্লাসের সাথে employee
টেবিলের নাম মেলে।
Entity ক্লাসের প্রপার্টি গুলি টেবিলের কলামের সাথে সঙ্গতিপূর্ণ হতে হবে। স্প্রিং ORM এবং Hibernate সাধারণত এটি অটোমেটিকভাবে ম্যাপ করে, তবে যদি প্রয়োজন হয়, তখন @Column অ্যানোটেশন ব্যবহার করে কলামের নাম পরিবর্তন করা যেতে পারে।
@Column(name = "emp_name")
private String name;
এখানে, name
প্রপার্টি emp_name
নামের কলামের সাথে ম্যাপ করা হচ্ছে।
প্রতিটি Entity ক্লাসে একটি Primary Key থাকতে হবে, যা সাধারণত @Id
অ্যানোটেশন দিয়ে চিহ্নিত করা হয়। GeneratedValue ব্যবহার করে Primary Key এর মান অটোমেটিকভাবে জেনারেট করা যায়।
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
এতে, id
ফিল্ডটি ডাটাবেসে স্বয়ংক্রিয়ভাবে জেনারেট হবে।
Entity গুলোর মধ্যে সম্পর্ক স্থাপন করা খুব গুরুত্বপূর্ণ। স্প্রিং ORM এবং Hibernate এ বিভিন্ন ধরনের সম্পর্কের জন্য সুনির্দিষ্ট অ্যানোটেশন রয়েছে, যেমন:
উদাহরণস্বরূপ:
@Entity
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "department")
private List<Employee> employees;
// Getters and Setters
}
এখানে, Department
ক্লাসে একটি One-to-Many সম্পর্ক তৈরি করা হয়েছে, যেখানে একটি Department
অনেক Employee
এর সাথে সম্পর্কিত।
Hibernate বা JPA-তে লেনদেনের সময় Lazy Loading এবং Eager Loading ব্যবহার করা হয় সম্পর্কযুক্ত Entity গুলোর লোডিং কন্ট্রোল করতে। Lazy Loading ব্যবহার করলে সম্পর্কযুক্ত Entity গুলো শুধুমাত্র প্রয়োজন হলে লোড হবে, আর Eager Loading ব্যবহার করলে সম্পর্কযুক্ত Entity গুলো একসাথে লোড হবে।
@OneToMany(fetch = FetchType.LAZY)
private List<Employee> employees;
এখানে, employees
ফিল্ডটি Lazy Loading
মোডে লোড হবে।
ডেটাবেসের টেবিলের Entity ক্লাস সরাসরি API বা ইউজার ইন্টারফেসের সাথে সংযুক্ত না করা উচিত। এর পরিবর্তে DTO ব্যবহার করা উচিত। DTO Entity ক্লাসের ডেটাকে প্রেজেন্টেশনের জন্য উপযোগী করে পরিবেশন করে।
public class EmployeeDTO {
private String name;
private String department;
// Constructor, Getters, and Setters
}
এতে, আপনি Entity ক্লাসের ডেটা DTO তে ট্রান্সফার করে প্রক্রিয়াটি আরও পরিষ্কার এবং সিস্টেমের নিরাপত্তা উন্নত করতে পারেন।
ডেটাবেসের টেবিলের জন্য সীমিত মান (এনাম) ব্যবহার করতে @Enumerated অ্যানোটেশন ব্যবহার করা যেতে পারে। এটি ডেটাবেসে সাধারণ স্ট্রিং ভ্যালু পরিবর্তে এনামের মান সংরক্ষণ করতে সহায়তা করে।
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Enumerated(EnumType.STRING)
private EmploymentType employmentType;
// Getters and Setters
}
public enum EmploymentType {
FULL_TIME,
PART_TIME
}
এখানে, employmentType
ফিল্ডটি FULL_TIME
অথবা PART_TIME
এনাম দিয়ে ধারণ করা হবে।
Entity Design এর সময় ডেটাবেস ট্রানজেকশন ম্যানেজমেন্টের বিষয়টি মাথায় রাখা উচিত। স্প্রিং ORM এ @Transactional অ্যানোটেশন ব্যবহার করে কার্যকর ট্রানজেকশন ম্যানেজমেন্ট করা যায়।
@Service
@Transactional
public class EmployeeService {
@Autowired
private EmployeeRepository employeeRepository;
public void saveEmployee(Employee employee) {
employeeRepository.save(employee);
}
}
এটি নিশ্চিত করে যে, ডেটাবেস অপারেশন একক ট্রানজেকশন হিসেবে পরিচালিত হবে এবং কোনো ত্রুটি ঘটলে তা রোলব্যাক হবে।
স্প্রিং ORM এ Entity Design করার জন্য কিছু গুরুত্বপূর্ণ Best Practices রয়েছে, যেমন Entity ক্লাসের নাম ও টেবিল নামের সঙ্গতি বজায় রাখা, Relationships সঠিকভাবে ম্যানেজ করা, Lazy এবং Eager Loading ব্যবহারে সঠিক সিদ্ধান্ত নেওয়া, DTO ব্যবহার করা, এবং ট্রানজেকশন ম্যানেজমেন্ট নিশ্চিত করা। এগুলোর মাধ্যমে আপনি কার্যকর ও সুসংগঠিত ডেটাবেস কাঠামো তৈরি করতে পারবেন, যা অ্যাপ্লিকেশনকে আরও স্কেলেবল এবং মেইনটেইনেবল করে তোলে।
Spring ORM ব্যবহার করে Java-তে ডাটাবেস অপারেশন কার্যকরীভাবে পরিচালনা করতে হলে, Performance Management, Caching, এবং Query Optimization অত্যন্ত গুরুত্বপূর্ণ। এই তিনটি বিষয় সঠিকভাবে পরিচালনা করলে অ্যাপ্লিকেশনের পারফরম্যান্স উল্লেখযোগ্যভাবে বৃদ্ধি পায় এবং ডাটাবেসের ওপর অপ্রয়োজনীয় চাপ কমানো যায়। নিচে এদের জন্য কিছু Best Practices দেওয়া হলো।
Hibernate বা JPA-তে Lazy Loading
ব্যবহার করার মাধ্যমে সম্পর্কিত অবজেক্টগুলো শুধুমাত্র যখন প্রয়োজন হবে তখন লোড করা হয়, যা ডাটাবেস থেকে অপ্রয়োজনীয় তথ্য লোড করা এড়ায়।
@OneToMany(fetch = FetchType.LAZY)
private Set<Order> orders;
Spring ORM-এ Batch Processing ব্যবহার করলে একাধিক ইনসার্ট বা আপডেট অপারেশন একসাথে করা যায়, ফলে ডাটাবেসের ওপর চাপ কমে এবং পারফরম্যান্স বৃদ্ধি পায়।
session.createQuery("insert into Employee (name, salary) select name, salary from TempEmployee")
.setBatchSize(50)
.executeUpdate();
Spring ORM-এ FetchType.LAZY এবং FetchType.EAGER দুইটি ফেচিং স্ট্র্যাটেজি আছে। LAZY
লোডিং ব্যবহার করা উত্তম যখন সম্পর্কিত ডেটা ততটা প্রয়োজনীয় নয়, আর EAGER
তখন ব্যবহার করুন যখন সম্পর্কিত ডেটা সবসময় প্রয়োজন।
ডাটাবেসের কানেকশন পুল সঠিকভাবে কনফিগার করা উচিত যাতে অতিরিক্ত কানেকশন ওপেন না হয় এবং প্রতিটি কানেকশন সহজেই পুনঃব্যবহার করা যায়। Spring-এর HikariCP
পুল ব্যবহার করা একটি ভাল পছন্দ।
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/your_db"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
<property name="maximumPoolSize" value="10"/>
</bean>
Hibernate-এর প্রথম স্তরের ক্যাশ (First-Level Cache) ডিফল্টভাবে সক্রিয় থাকে এবং এটি ডাটাবেস সেশন-ভিত্তিক। একবার কোন ডেটা ক্যাশে চলে গেলে, সেই সেশনে পুনরায় একই ডেটা রিকোয়েস্ট করলে ডাটাবেসে আর নতুন করে ক্যুয়েরি পাঠানো হয় না।
session.get(Employee.class, 1); // This result will be cached in the session.
Hibernate-এ Second-Level Cache বিভিন্ন সেশন শেয়ার করতে সক্ষম হয়, যা ডাটাবেসে কম লোড করতে সাহায্য করে। এটি পছন্দমতো ক্যাশ ইঞ্জিন যেমন EHCache, Infinispan, বা Redis ব্যবহার করে কনফিগার করা যায়।
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
Query Cache ব্যবহার করে একটি নির্দিষ্ট কুয়েরির রেজাল্ট ক্যাশে রাখা যায়, যা একাধিক বার একই কুয়েরি চালানোর সময় পারফরম্যান্স বাড়াতে সাহায্য করে।
List<Employee> employees = session.createQuery("FROM Employee WHERE department = :dept")
.setParameter("dept", "IT")
.setCacheable(true)
.list();
Redis বা EhCache এর মাধ্যমে আপনি একটি দ্রুত, ইন-মেমরি ক্যাশ লেয়ার তৈরি করতে পারেন, যা Spring Cache Abstraction ব্যবহার করে Spring ORM-এ সহজে সংহত করা যায়।
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
@EnableCaching
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
return new RedisCacheManager(redisTemplate());
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// configure redis template here
return redisTemplate;
}
}
ডাটাবেস টেবিলে সঠিকভাবে Indexing করলে কুয়েরির পারফরম্যান্স উল্লেখযোগ্যভাবে বৃদ্ধি পায়, বিশেষ করে যখন ডাটাবেসে অনেক রেকর্ড থাকে। এক্সিকিউটেড কুয়েরির স্লো পারফরম্যান্সের জন্য ইনডেক্স অবশ্যই ব্যবহৃত হওয়া উচিত।
CREATE INDEX idx_department ON employees(department);
Hibernate-এ JPQL (Java Persistence Query Language) বা Criteria API ব্যবহার করার মাধ্যমে কোডটি ডাটাবেস নিরপেক্ষ এবং অধিক অপ্টিমাইজ করা যায়।
// JPQL Query
List<Employee> employees = session.createQuery("FROM Employee WHERE department = :dept")
.setParameter("dept", "IT")
.getResultList();
// Criteria API Query
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Employee> query = builder.createQuery(Employee.class);
Root<Employee> root = query.from(Employee.class);
query.select(root).where(builder.equal(root.get("department"), "IT"));
List<Employee> employees = session.createQuery(query).getResultList();
এখনো অনেকে অতিরিক্ত বা অপ্রয়োজনীয় JOIN ব্যবহার করে থাকেন। সম্পর্কিত ডেটা টেনে আনতে INNER JOIN বা LEFT JOIN ব্যবহার করার আগে, শুধুমাত্র প্রয়োজনীয় ডেটাই যুক্ত করুন।
SELECT e FROM Employee e JOIN e.orders o WHERE o.status = 'Completed'
Spring ORM-এ ডাটাবেসের পারফরম্যান্স বিশ্লেষণের জন্য বিভিন্ন টুল ব্যবহার করা যেতে পারে, যেমন Hibernate Profiler বা Database Query Optimizer। এগুলো কোড ও কুয়েরি লেভেলে পারফরম্যান্স চেক করতে সাহায্য করে।
Spring ORM এ Performance Management, Caching, এবং Query Optimization-এর জন্য কিছু গুরুত্বপূর্ণ Best Practices হলো:
এই Best Practices অনুসরণ করলে Spring ORM ব্যবহারকারী ডাটাবেস অপারেশনকে আরও কার্যকর এবং স্কেলেবল করতে পারবেন।
স্প্রিং ORM এবং Hibernate ব্যবহারের সময় এক্সসেপশন হ্যান্ডলিং এবং ট্রান্সাকশন ম্যানেজমেন্ট অত্যন্ত গুরুত্বপূর্ণ। সঠিকভাবে এক্সসেপশন হ্যান্ডলিং এবং ট্রান্সাকশন ম্যানেজমেন্ট করলে কোড আরও স্থিতিশীল এবং কার্যকরী হয়। এখানে কিছু সেরা পদ্ধতি আলোচনা করা হলো যা স্প্রিং ORM এবং Hibernate ব্যবহারের সময় মেনে চলা উচিত।
@Repository
এনোটেশন ব্যবহার করাSpring-এর @Repository
এনোটেশন ব্যবহার করলে Hibernate বা JPA এর DataAccessException
প্রকারের এক্সসেপশন গুলো Spring এর DataAccessException
এ রূপান্তরিত হয়ে যায়। এটি এক্সসেপশন হ্যান্ডলিং সহজ এবং এককভাবে পরিচালনা করতে সাহায্য করে।
@Repository
public class UserDao {
@Autowired
private SessionFactory sessionFactory;
public User findUserById(int id) {
try {
Session session = sessionFactory.getCurrentSession();
return session.get(User.class, id);
} catch (Exception e) {
throw new DataAccessException("Error finding user with id: " + id, e);
}
}
}
নিজস্ব এক্সসেপশন তৈরি করা আপনার অ্যাপ্লিকেশনের জন্য আরও পরিষ্কার এবং প্রাঞ্জল এক্সসেপশন হ্যান্ডলিং নিশ্চিত করতে সহায়ক। এতে করে আপনি বিভিন্ন ধরনের ডেটাবেস বা ট্রান্সাকশন সম্পর্কিত ত্রুটি স্পষ্টভাবে ক্যাপচার এবং হ্যান্ডল করতে পারেন।
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}
@ExceptionHandler
ব্যবহার করাSpring MVC এ @ExceptionHandler
ব্যবহার করে এক্সসেপশন হ্যান্ডলিং আরও নির্দিষ্টভাবে করা যায়। এটি কন্ট্রোলারের মধ্যে নির্দিষ্ট এক্সসেপশনগুলোর জন্য কাস্টম রেসপন্স ফিরিয়ে দিতে সাহায্য করে।
@Controller
public class UserController {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<String> handleUserNotFoundException(UserNotFoundException e) {
return new ResponseEntity<>("User not found: " + e.getMessage(), HttpStatus.NOT_FOUND);
}
@GetMapping("/user/{id}")
public User getUser(@PathVariable int id) {
User user = userService.findUserById(id);
if (user == null) {
throw new UserNotFoundException("User with id " + id + " does not exist.");
}
return user;
}
}
এক্সসেপশনগুলোর সঠিক লগিং গুরুত্বপূর্ণ, যা ডিবাগিং এবং সমস্যার সমাধানে সহায়ক হয়। স্প্রিং লজিং সুবিধা, যেমন SLF4J
, ব্যবহার করতে পারেন।
private static final Logger logger = LoggerFactory.getLogger(UserDao.class);
public User findUserById(int id) {
try {
Session session = sessionFactory.getCurrentSession();
return session.get(User.class, id);
} catch (Exception e) {
logger.error("Error finding user with id: {}", id, e);
throw new DataAccessException("Error finding user with id: " + id, e);
}
}
@Transactional
এনোটেশন ব্যবহার করাSpring এর @Transactional
এনোটেশন সহজ এবং কার্যকরী ট্রান্সাকশন ম্যানেজমেন্ট প্রদান করে। এটি অটোমেটিক ট্রান্সাকশন কমপ্লিশন, রোলব্যাক এবং কমিট পরিচালনা করে।
@Service
public class UserService {
@Autowired
private UserDao userDao;
@Transactional
public void updateUser(User user) {
userDao.update(user);
// other operations
}
}
@Transactional
এনোটেশনটি স্বয়ংক্রিয়ভাবে ট্রান্সাকশন শুরু, কমপ্লিশন এবং রোলব্যাক করতে সক্ষম।ট্রান্সাকশন একাধিক স্তরে বিভক্ত করা উচিত নয়। একটি ট্রান্সাকশন শুধুমাত্র এক ধরনের লজিকাল অপারেশন দ্বারা সম্পন্ন হওয়া উচিত, যেমন একাধিক ডেটাবেস আপডেট করা, কিন্তু যদি একাধিক সিস্টেমের মধ্যে অপারেশন থাকে, তবে আলাদা ট্রান্সাকশন ব্যবহার করা উচিত।
@Transactional
public void transferFunds(Account fromAccount, Account toAccount, double amount) {
fromAccount.withdraw(amount);
toAccount.deposit(amount);
}
@Transactional
এনোটেশনের মাধ্যমে আপনি কোন এক্সসেপশনের উপর ভিত্তি করে ট্রান্সাকশন রোলব্যাক নির্ধারণ করতে পারেন। ডিফল্টভাবে, Spring রUNTIME এক্সসেপশনগুলো রোলব্যাক করবে, কিন্তু চেকড এক্সসেপশনগুলোর জন্য আপনাকে বিশেষভাবে রোলব্যাক করতে হবে।
@Transactional(rollbackFor = { SQLException.class })
public void updateUser(User user) throws SQLException {
// database update logic
}
যখন আপনার ট্রান্সাকশন হ্যান্ডলিং কাস্টমাইজ করতে হয়, তখন PlatformTransactionManager
এবং TransactionDefinition
ব্যবহার করে প্রোগ্রাম্যাটিক ট্রান্সাকশন ম্যানেজমেন্ট করতে পারেন।
@Autowired
private PlatformTransactionManager transactionManager;
public void transferFunds(Account fromAccount, Account toAccount, double amount) {
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
fromAccount.withdraw(amount);
toAccount.deposit(amount);
transactionManager.commit(status); // Commit the transaction
} catch (Exception e) {
transactionManager.rollback(status); // Rollback on exception
throw e;
}
}
@EnableTransactionManagement
Spring XML কনফিগারেশনে @EnableTransactionManagement
এনোটেশন ব্যবহার করা যেতে পারে। এটি Spring Container-এ ট্রান্সাকশন ম্যানেজমেন্ট সক্রিয় করে।
@Configuration
@EnableTransactionManagement
public class AppConfig {
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource();
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
স্প্রিং ORM এ এক্সসেপশন হ্যান্ডলিং এবং ট্রান্সাকশন ম্যানেজমেন্টে কিছু সেরা পদ্ধতি রয়েছে যা ডেভেলপারদের সাহায্য করে কোডের কার্যকারিতা এবং স্থিতিশীলতা উন্নত করতে। @Transactional
এনোটেশন এবং প্রোগ্রাম্যাটিক ট্রান্সাকশন ম্যানেজমেন্টের সঠিক ব্যবহার, কাস্টম এক্সসেপশন তৈরি, এবং এক্সসেপশন লগিংয়ের মাধ্যমে সহজেই শক্তিশালী এবং ভুলমুক্ত অ্যাপ্লিকেশন তৈরি করা সম্ভব।
Read more